home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 6 / MacMania 6.toast / / Multimedia & Desktop / VideoToolbox / (Demos) / FlickeringGrating.c < prev    next >
C/C++ Source or Header  |  1997-07-02  |  8KB  |  242 lines

  1. /*
  2. FlickeringGrating.c
  3. This demo displays a research-grade visual stimulus. If you just want to know
  4. how to load the clut and display a pattern, then you should start by reading
  5. Grating.c, which is much shorter and simpler.
  6. Copyright (c) 1989-1993 Denis G. Pelli
  7. HISTORY:
  8. 11/89     Lan & Denis wrote it.
  9. 23.1.90    dgp        Use second screen only if available.
  10. 4/9/90    dgp        Changed WindowPtr to CWindowPtr. Made big arrays static. Reduced
  11.                 default memory allocation to 1 megabyte. Use any 8-bit screen,
  12.                 preferably not the main screen.
  13. 4/23/90    dgp        Added optional timing. Centered the image. Left clut entries 0 and 
  14.                 clutSize-1 alone, so background doesn't flash. Asked if ISR Video 
  15.                 Attenuator is present.
  16. 10/11/90 dgp    Added fpu test.
  17. 10/29/90 dgp    Added CenterRectInRect().
  18. 10/30/90 dgp    Changed call to SetLuminances() to SetLuminancesAndRange() so that
  19.                 the range is now kept fixed throughout all the frames, to avoid
  20.                 flashes.
  21. 8/24/91    dgp        Made compatible with THINK C 5.0.
  22.                 If possible, use ReadLuminanceRecord().
  23. 4/26/92    dgp        RestoreCluts().
  24. 8/27/92    dgp        replace SysEnvirons() by Gestalt()
  25. 12/30/92 dgp    made more like Filter, using a small console so that, if necessary,
  26.                 both the console and the grating will fit on the main monitor.
  27. 2/7/93    dgp        replaced SetOnePixel by SetPixelsQuickly
  28. 7/7/93    dgp        added code for compatibility with Radius PowerView, a SCSI video box.
  29. 9/5/94 dgp removed assumption in printf's that int==short.
  30. 11/17/94 dgp Josh Solomon reported a stack overflow, so I added a calls to StackGrow
  31. and assert.
  32. 1/11/95    dgp    Tidied up various things. Now switch to color mode if using an ISR Attenuator.
  33. 4/11/95 dgp Save and restore the display depth and color mode.
  34. 6/1/95 dgp added code to support profiling in CodeWarrior.
  35. 6/14/95 dgp added call to ShieldCursor().
  36. 4/10/97    dgp    Eliminate stuff that was conditional on !UNIVERSAL_HEADERS.
  37. 7/1/97    dgp    After GDOpenWindow, now call ShowWindow, since GDOpenWindow no longer does.
  38. 7/1/97    dgp    Before EraseRect, replaced call to PmBackColor by calls to Index2Color and 
  39.             RGBBackColor. I don't understand why PmBackColor wasn't working correctly.
  40.  
  41. */
  42. #include "VideoToolbox.h"
  43. #include "Luminance.h"
  44. #if (THINK_C || THINK_CPLUS || SYMANTEC_C)
  45.     #define SYMANTEC_C_PROFILE        0            // optionally, report timing
  46.     #include <profile.h>
  47. #endif
  48. #if __MWERKS__
  49.     #include <profiler.h>
  50. #endif
  51. #include <LowMem.h>        // LMGetMBarHeight,LMSetMBarHeight
  52.  
  53. #define SIZE         400            // size of grating, in pixels
  54. #define TMAX        6*67        // duration, in frames, typically at 67 Hz
  55. #define REPETITIONS    1            // Number of times to repeat the animation
  56.  
  57. void main(void);
  58. void FlickeringGrating(void);
  59. typedef struct{
  60.     ColorSpec table[256];
  61. }ColorSpecTable;
  62.  
  63. void main(void)
  64. {
  65.     StackGrow(40000L+2*SIZE*sizeof(double)+SIZE*sizeof(long)+sizeof(LuminanceRecord)+TMAX*sizeof(Ptr));
  66.     MaxApplZone();
  67.     Require(gestalt8BitQD);
  68.     FlickeringGrating();
  69. }
  70.     
  71. void FlickeringGrating(void)
  72. {
  73.     register int i;
  74.     int j,tmax,clutSize,error,oldPixelSize,oldIsColor;
  75.     double fX[SIZE],fY[SIZE];
  76.     double LMid,LMin,LMax,dL,a,contrast;
  77.     CWindowPtr window=NULL;
  78.     WindowPtr oldPort=NULL;
  79.     GDHandle device=NULL;
  80.     LuminanceRecord LR,*LP;
  81.     ColorSpecTable *tables[TMAX];    // an array of pointers to ColorSpec tables
  82.     char string[100];
  83.     Rect r;
  84.     Boolean attenuatorInstalled;
  85.     long finalTicks;
  86.     Point pt;
  87.     RGBColor rgb;
  88.     
  89.     assert(StackSpace()>8000);
  90.     #if SYMANTEC_C_PROFILE
  91.         InitProfile(200,3);    /* only needed if you want timing info */
  92.         _profile=0;
  93.     #endif
  94.     #if __MWERKS__ && __profile__
  95.         ProfilerInit(collectDetailed,bestTimeBase,110,20);
  96.         ProfilerSetStatus(0);
  97.     #endif
  98.     /* INITIALIZE QuickDraw */
  99.     MaximizeConsoleHeight();
  100.     #if (THINK_C || THINK_CPLUS || SYMANTEC_C)
  101.         console_options.title="\pFlickeringGrating";
  102.         console_options.nrows = 5;
  103.     #elif __MWERKS__
  104.         SIOUXSettings.rows=5;
  105.         SIOUXSettings.autocloseonquit=0;
  106.         SIOUXSettings.showstatusline=0;
  107.         SIOUXSettings.asktosaveonclose=0;
  108.     #else
  109.         InitGraf(&qd.thePort);
  110.         InitFonts();
  111.         InitWindows();
  112.         InitCursor();
  113.     #endif
  114.     printf("\n");    // make sure that oldPort is the console
  115.     GetPort(&oldPort);
  116.     printf("Welcome to FlickeringGrating.\n");
  117.  
  118.     for(i=8;i>=0;i--){
  119.         // look for a screen with 8-bit pixels.
  120.         device=GetScreenDevice(i);
  121.         if(device == NULL)continue;
  122.         if((*(*device)->gdPMap)->pixelSize==8)break;
  123.     }
  124.     do{
  125.         if(GetScreenDevice(1)!=NULL)i=ChooseScreen(i,"Which screen?");
  126.         else i=0;
  127.         device=GetScreenDevice(i);
  128.     }while(device==NULL);
  129.     oldIsColor=TestDeviceAttribute(device,gdDevType);
  130.     oldPixelSize=(*(*device)->gdPMap)->pixelSize;
  131.     if(NewPaletteManager() && (oldPixelSize!=8 || !oldIsColor))
  132.         SetDepth(device,8,1<<gdDevType,1);
  133.     if(device==NULL || (*(*device)->gdPMap)->pixelSize!=8)
  134.         PrintfExit("Sorry, I require 8 bits/pixel.\n");
  135.     sprintf(string,"LuminanceRecord%d.h",i);
  136.     LP=&LR;
  137.     i=ReadLuminanceRecord(string,LP,0);    /* try to read correct file */
  138.     if(i<=0){
  139.         #include "LuminanceRecord1.h"
  140.     }
  141.     attenuatorInstalled=Choose(0,"Have you installed an ISR Video Attenuator?\n",noYes,2);
  142.     printf("Using luminance calibration for screen %d calibrated %s by %s.\n"
  143.         ,(int)LP->screen,LP->date,LP->notes);
  144.     if(!attenuatorInstalled){
  145.         LP->r=0.0;
  146.         LP->g=1.0;
  147.         LP->b=0.0;
  148.     }
  149.     window=GDOpenWindow(device);
  150.     ShowWindow((WindowPtr)window);
  151.     #if SYMANTEC_C_PROFILE
  152.         _profile=1;
  153.     #endif
  154.     #if __MWERKS__ && __profile__
  155.         ProfilerSetStatus(1);
  156.     #endif
  157.  
  158.     /* load clut with linear gray scale */
  159.     // We'll leave clut entries 0 (white) and clutSize-1 (black) alone,
  160.     // since they are used heavily by Apple's stuff. Window frames
  161.     // will mostly look normal if we leave those two entries alone.
  162.     clutSize=GDClutSize(device);
  163.     SetLuminances(device,LP,1,clutSize-2,LP->LMin,LP->LMax);
  164.         
  165.     /* Display a sinusoid with a gaussian envelope */
  166.     // Compute the image.
  167.     SetPort((WindowPtr)window);
  168.     i=1+(long)(0.5+(clutSize-3)*0.5);
  169.     //PmBackColor(i);
  170.     Index2Color(i,&rgb);
  171.     RGBBackColor(&rgb);
  172.     EraseRect(&window->portRect);
  173.     SetRect(&r,0,0,SIZE,SIZE);
  174.     CenterRectInRect(&r,&window->portRect);
  175.     for(i=0;i<SIZE;i++){
  176.         a=(i-SIZE/2)/(SIZE/6.);
  177.         fY[i]=exp(-a*a);
  178.         fX[i]=fY[i]*sin((i-SIZE/2)*(2.0*PI/80.0));
  179.     }
  180.     assert(StackSpace()>4L*SIZE+4000);
  181.     pt.h=pt.v=0;
  182.     LocalToGlobal(&pt);
  183.     ShieldCursor(&r,pt);
  184.     for(j=0;j<SIZE;j++){
  185.         unsigned long row[SIZE];
  186.         for(i=0;i<SIZE;i++) row[i]=1+(long)(0.5+(clutSize-3)*0.5*(1.0+fY[j]*fX[i]));
  187.         SetPixelsQuickly(r.left,j+r.top,row,SIZE);
  188.     }
  189.     ShowCursor();
  190.     // Allocate ColorSpec tables, one for each frame
  191.     for(i=0;i<TMAX;i++){
  192.         tables[i]=(ColorSpecTable *)NewPtr(sizeof(ColorSpecTable));
  193.         if(tables[i]==NULL){
  194.             printf("Only room for %d lookup tables (one per frame) ... continuing.\n",i);
  195.             break;
  196.         }
  197.     }
  198.     tmax=i;
  199.     // Compute lookup tables.
  200.     LMid=(LP->LMax+LP->LMin)/2.0;
  201.     contrast=(LP->LMax-LP->LMin)/(LP->LMax+LP->LMin);
  202.     LMax=LMid*(1.0+contrast);
  203.     LMin=LMid*(1.0-contrast);
  204.     SetLuminancesAndRange(device,LP,1,clutSize-2,LMid,LMid,LMin,LMax);    // blank screen
  205.     for(i=0;i<tmax;i++){
  206.         a=6.0*(i-tmax/2)/tmax;
  207.         dL=LMid*contrast*exp(-a*a)*sin((i-tmax/2)*(2.0*PI*3.0*0.015));
  208.         SetLuminancesAndRange(NULL,LP,1,clutSize-2,LMid-dL,LMid+dL,LMin,LMax);
  209.         *tables[i]= *(ColorSpecTable *)LP->table;
  210.     }
  211.     printf("Now displaying the animation ...\n");
  212.     Delay(60,&finalTicks);
  213.     for(j=0;j<REPETITIONS;j++){
  214.         for(i=0;i<tmax;i++){
  215.             // This is a thinly disguished call to GDSetEntries.
  216.             LoadLuminances(device,(LuminanceRecord *) tables[i],1,clutSize-2);
  217.         }
  218.     }
  219.     #if SYMANTEC_C_PROFILE
  220.         _profile=0;
  221.     #endif
  222.     #if __MWERKS__ && __profile__
  223.         ProfilerSetStatus(0);
  224.     #endif
  225.     for(i=0;i<tmax;i++)DisposPtr((Ptr)tables[i]);
  226.     SetPort(oldPort);
  227.     GDDisposeWindow(window);
  228.     if(NewPaletteManager())
  229.         error=SetDepth(device,oldPixelSize,1<<gdDevType,oldIsColor);    // restore
  230.     else RestoreCluts();
  231.     #if (THINK_C || THINK_CPLUS || SYMANTEC_C) && !SYMANTEC_C_PROFILE
  232.         if(tmax==TMAX)abort();
  233.     #endif
  234.     #if __MWERKS__ && __profile__
  235.         ProfilerDump("\pFlickeringGrating.Profile");
  236.         ProfilerTerm();
  237.     #endif
  238.     #if __MWERKS__
  239.         if(tmax==TMAX)SIOUXSettings.autocloseonquit=1;
  240.     #endif
  241. }
  242.